package com.blunka.framework.client.db.druid.dbutils;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import javax.sql.DataSource;

import org.apache.commons.dbutils.BasicRowProcessor;
import org.apache.commons.dbutils.CamelBeanProcessor;
import org.apache.commons.dbutils.DbUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.RowProcessor;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.StringArrayListHandler;
import org.apache.commons.dbutils.handlers.StringMapHandler;
import org.apache.commons.dbutils.handlers.StringMapListHandler;
import org.apache.log4j.Logger;

import com.alibaba.druid.pool.DruidDataSourceFactory;
import com.blunka.framework.client.db.entity.BatchSqlEntity;

/**
 *
 *
 * @平台：统一开发平台
 * @文件名称：SqlLiteServerDbHelper.java
 * @文件描述：SqlLite数据库
 * @author xuqiang
 * @日期：2018年5月25日下午4:56:13
 *
 */
public class ServerDbHelper implements IServiceDbHelper{
	private static final Logger logger = Logger.getLogger(ServerDbHelper.class);

	/**
     * Singleton processor instance that handlers share to save memory.
     */
    public static final RowProcessor<Object> BEAN_ROW_PROCESSOR = new BasicRowProcessor(new CamelBeanProcessor());

	public DataSource ds;

	/*static{
		try{
			Properties p = new Properties();
			p.put("driverClassName", "org.sqlite.JDBC");
			p.put("url", "jdbc:sqlite:"+DesignUtils.getDir()+"/res/db/thumnp.db");
			ds = DruidDataSourceFactory.createDataSource(p);
		}catch(Exception e){
			logger.error("数据库连接失败",e);
		}
	}*/

	/**
	 * 初始化数据库连接
	 * @param p
	 * @throws Exception
	 */
	public void initDataSource(Properties p)throws Exception{
		ds = DruidDataSourceFactory.createDataSource(p);
	}

	/**
	 * 获取数据源
	 * @return 数据源对象
	 */
	public DataSource getDataSource() {
        return ds;
    }

	/**
	 * 取得数据库连接
	 * @return 数据库连接对象
	 */
	public Connection getConn(){
		try {
			return ds.getConnection();
		} catch (SQLException e) {
		    logger.error(e.getMessage(), e);
			return null;
		}
	}

	/**
	 * 释放数据库连接
	 * @param conn 要释放的数据库连接
	 */
	public void closeConn(Connection conn){
		DbUtils.closeQuietly(conn);
	}

    /**
     * 执行 SELECT 语句，返回单条查询结果为Map对象
     *
     * @param sql 即将被执行的sql语句.
     * @return 返回Map对象，出错则返回null
     */
    public Map<String, String> getItemMap(String sql){
    	return getItemMap(sql, (Object[]) null);
    }

    /**
     * 带入指定的参数对象，执行 SELECT 语句，返回单条查询结果为Map对象
     *
     * @param sql 即将被执行的sql语句.
     * @param param 参数对象.
     * @return 返回Map对象，出错则返回null
     */
    public Map<String, String> getItemMap(String sql, Object param) {
        return getItemMap(sql, new Object[] { param });
    }

    /**
     * 带入指定的参数数组，执行 SELECT 语句，返回单条查询结果为Map对象
     *
     * @param sql 即将被执行的sql语句.
     * @param params 参数数组.
     * @return 返回Map对象，出错则返回null
     */
    public Map<String, String> getItemMap(String sql, Object... params) {
        debug(sql, params);
        QueryRunner run = new QueryRunner(ds);
        try {
            return run.query(sql, new StringMapHandler(), params);
        } catch (SQLException ex) {
            logger.error(ex.getMessage(), ex);
            return null;
        }
    }

    /**
     * 带入指定的参数对象，执行 SELECT 语句，并把查询结果返回为字符串数组列表
     *
     * @param sql 即将被执行的sql语句.
     * @param param 参数对象.
     * @return 返回字符串数组的列表，出错则返回空列表
     */
    public List<String[]> getArrayList(String sql, Object param)throws SQLException {
        return getArrayList(sql, new Object[] { param });
    }

    /**
     * 带入指定的参数数组，执行 SELECT 语句，并把查询结果返回为字符串数组列表
     *
     * @param sql 即将被执行的sql语句.
     * @param params 参数数组.
     * @return 返回字符串数组的列表，出错则返回空列表
     */
    public List<String[]> getArrayList(String sql, Object... params)throws SQLException {
        debug(sql, params);
        QueryRunner run = new QueryRunner(ds);
        return run.query(sql, new StringArrayListHandler(), params);
    }

    /**
     * 带入指定的参数数组，执行 INSERT, UPDATE, 或者 DELETE 语句
     *
     * @param sql 即将被执行的sql语句.
     * @param params 参数数组.
     * @return 影响的行数，-1表示出错
     */
    public int[] batch(String sql, List<Object[]> params) {
        debug(sql, new Object[] {"batch sql, count:" + ((params==null)?-1:params.size())});
        QueryRunner run = new QueryRunner(ds);
        try {
            Object[][] o = new Object[params.size()][];
            for (int i=0; i<params.size(); i++) {
                o[i] = params.get(i);
            }
            return run.batch(sql, o) ;
        } catch (SQLException ex) {
            logger.error(ex.getMessage(), ex);
            return null;
        }
    }

    /**
     *
     * @param entity
     * @return 批量处理sql
     * @throws Exception
     */
    public int[] batch(List<BatchSqlEntity> entity)throws Exception {
   	 QueryRunner run = new QueryRunner(ds);
   	 return run.batch(entity);
   }

    /**
     * 批量执行sql
     * @param sql
     * @return
     * @throws Exception
     */
    public int[] batch(ArrayList<String> sql)throws Exception{
    	QueryRunner run = new QueryRunner(ds);

    	return run.batch(sql);
    }

    /**
     * 执行 SELECT 语句，并把查询结果返回为Map列表
     *
     * @param sql 即将被执行的sql语句.
     * @return 返回Map的列表，出错则返回空列表
     */
    public List<Map<String, String>> getMapList(String sql) {
        return getMapList(sql, (Object[]) null);
    }

    /**
     * 带入指定的参数对象，执行 SELECT 语句，并把查询结果返回为Map列表
     *
     * @param sql 即将被执行的sql语句.
     * @param param 参数对象.
     * @return 返回Map的列表，出错则返回空列表
     */
    public List<Map<String, String>> getMapList(String sql, Object param) {
        return getMapList(sql, new Object[] { param });
    }

    /**
     * 带入指定的参数数组，执行 SELECT 语句，并把查询结果返回为Map列表
     *
     * @param sql 即将被执行的sql语句.
     * @param params 参数数组.
     * @return 返回Map的列表，出错则返回空列表
     */
    public List<Map<String, String>> getMapList(String sql, Object... params) {
        debug(sql, params);
        QueryRunner run = new QueryRunner(ds);
        try {
            return run.query(sql, new StringMapListHandler(), params);
        } catch (SQLException ex) {
            return new ArrayList<Map<String, String>>();
        }
    }

    /**
     * 执行 SELECT 语句，并把查询结果返回为字符串数组列表
     *
     * @param sql 即将被执行的sql语句.
     * @return 返回字符串数组的列表，出错则返回空列表
     */
    public List<String[]> getArrayList(String sql)throws SQLException {
        return getArrayList(sql, (Object[]) null);
    }

    /**
     * 执行 INSERT, UPDATE, 或者 DELETE 语句
     *
     * @param sql 即将被执行的sql语句.
     * @return 影响的行数，-1表示出错
     */
    public int execute(String sql) {
        return execute(sql, (Object[]) null);
    }

    /**
     * 带入指定的参数对象，执行 INSERT, UPDATE, 或者 DELETE 语句
     *
     * @param sql 即将被执行的sql语句.
     * @param param 参数对象.
     * @return 影响的行数，-1表示出错
     */
    public int execute(String sql, Object param) {
        return execute(sql, new Object[] { param });
    }

    /**
     * 带入指定的参数数组，执行 INSERT, UPDATE, 或者 DELETE 语句
     *
     * @param sql 即将被执行的sql语句.
     * @param params 参数数组.
     * @return 影响的行数，-1表示出错
     */
    public int execute(String sql, Object... params) {
        debug(sql, params);
        QueryRunner run = new QueryRunner(ds);
        try {
            return run.update(sql, params);
        } catch (SQLException ex) {
            logger.error(ex.getMessage(), ex);
            return -1;
        }
    }

    /**
     * 给定SQL和指定的类，就可以返回一个对象（如果结果集有多行，则只返回首行）。
     * @param <T>
     *
     * @param sql 即将被执行的sql语句.
     * @param type 指定类
     * @return 获取的对象.(如果结果集为空，则返回null)
     */
    public <T> T getBean(String sql, Class<T> type)
    {
    	return getBean(sql, type, (Object[]) null);
    }

    /**
     * 给定SQL和指定的类，就可以返回一个对象（如果结果集有多行，则只返回首行）。
     * @param sql 即将被执行的sql语句.
     * @param type 指定类
     * @param param 参数
     * @return 获取的对象.(如果结果集为空，则返回null)
     */
    public <T> T getBean(String sql, Class<T> type, Object param)
    {
        return getBean(sql, type, new Object[] { param });
    }

    /**
     * 给定SQL和指定的类，就可以返回一个对象（如果结果集有多行，则只返回首行）。
     * @param sql 即将被执行的sql语句.
     * @param type 指定类
     * @param params 参数数组
     * @return 获取的对象.(如果结果集为空，则返回null)
     */
    public <T> T getBean(String sql, Class<T> type, Object... params)
    {
    	QueryRunner run = new QueryRunner(ds);
        try {
            return run.query(sql, new BeanHandler<T>(type, BEAN_ROW_PROCESSOR), params);
        } catch (SQLException ex) {
            logger.error(ex.getMessage(), ex);
            return null;
        }
    }

    /**
     * 给定SQL和指定的类，就可以返回一个对象列表
     * @param sql 即将被执行的sql语句.
     * @param type 指定类
     * @param params 参数数组
     * @return 获取的对象列表.(如果结果集为空，则返回null)
     */
    public <T> List<T> getBeanList(String sql, Class<T> type, Object... params){
    	QueryRunner run = new QueryRunner(ds);
        try {
            return run.query(sql, new BeanListHandler<T>(type, BEAN_ROW_PROCESSOR), params);
        } catch (SQLException ex) {
            logger.error(ex.getMessage(), ex);
            return null;
        }
    }

    /**
     * 给定SQL和指定的类，就可以返回一个对象列表
     *
     * @param sql 即将被执行的sql语句.
     * @param type 指定类
     * @return 获取的对象列表.(如果结果集为空，则返回长度为0的list)
     */
    public <T> List<T> getBeanList(String sql, Class<T> type)
    {
    	return getBeanList(sql, type, (Object[]) null);
    }

    /**
     * 给定SQL和指定的类，就可以返回一个对象列表
     * @param sql 即将被执行的sql语句.
     * @param type 指定类
     * @param param 查询参数
     * @return 获取的对象列表.(如果结果集为空，则返回长度为0的list)
     */
    public <T> List<T> getBeanList(String sql, Class<T> type, Object param)
    {
        return getBeanList(sql, type, new Object[] { param });
    }


    /**
     * 输出debug信息
     * @param sql 执行的SQL语句
     * @param params 执行的参数
     */
    private void debug(String sql, Object... params){
        if (logger.isDebugEnabled()) {
            if (params==null) {
                params = new Object[]{};
            }
            StringBuilder sb = new StringBuilder(400);
            sb.append(sql);
            if (params.length!=0) {
                sb.append(" [params:");
                for(Object obj : params){
                    sb.append(obj==null?"<null>":obj.toString()).append(", ");
                }
                sb.setLength(sb.length()-2);
                sb.append("]");
            }
            logger.debug(sb.toString());
        }
    }
}
